package com.xiehua.task.client;

import com.xiehua.task.agent.PostMan;
import com.xiehua.task.client.handler.BroadcastHandler;
import com.xiehua.task.client.handler.TaskPushReqHandler;
import com.xiehua.task.client.handler.TaskRegRespHandler;
import com.xiehua.task.intf.AbsBusinessHandler;
import com.xiehua.task.prop.XiehuaConfig;
import com.xiehua.task.protocol.TaskPacket;
import com.xiehua.task.protocol.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tio.client.intf.ClientAioHandler;
import org.tio.core.ChannelContext;
import org.tio.core.intf.Packet;

import java.util.HashMap;
import java.util.Map;

import static com.xiehua.task.prop.XiehuaConfig.KEY_CLIENT_SECRET_KEY;

/**
 * @author Mr.zhang
 * @date 2018 03-27
 */
public class ClientHandler extends PostMan implements ClientAioHandler {

    private static Logger log = LoggerFactory.getLogger(ClientHandler.class);

    private static Map<Byte, AbsBusinessHandler<?>> handlerMap;

    static {
        handlerMap = new HashMap<>();
        handlerMap.put(Type.BROADCAST, new BroadcastHandler());
        handlerMap.put(Type.TASK_REG_RESP, new TaskRegRespHandler());
        handlerMap.put(Type.TASK_PUSH_REQ, new TaskPushReqHandler());
    }

    /**
     * 处理消息
     */
    @Override
    public void handler(Packet packet, ChannelContext channelContext) throws Exception {
        TaskPacket xiehuakPacket = (TaskPacket) packet;
        Byte type = xiehuakPacket.getType();
        if (Type.BROADCAST == type) {
            handlerMap.get(Type.BROADCAST).handler(xiehuakPacket, channelContext);
            return;
        }
        //valida data
        if (xiehuakPacket.getSignData() == null) {
            log.warn("消息包sign缺失");
            return;
        }
        if (!xiehuakPacket.getSignData().equals(xiehuakPacket.signData(XiehuaConfig.getInstance().get(KEY_CLIENT_SECRET_KEY)))) {
            log.warn("风险:消息被篡改");
            return;
        }
        AbsBusinessHandler<?> bsHandler = handlerMap.get(type);
        bsHandler.handler(xiehuakPacket, channelContext);
        return;
    }

    /**
     * 此方法如果返回null，框架层面则不会发心跳；如果返回非null，框架层面会定时发本方法返回的消息包
     */
    @Override
    public TaskPacket heartbeatPacket() {
        return TaskPacket.heartbeatPacket();
    }
}
